package me.zxk.smartagriculture.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zxk.smartagriculture.dto.comment.CommentRequest;
import me.zxk.smartagriculture.dto.comment.CommentResponse;
import me.zxk.smartagriculture.entity.Comment;
import me.zxk.smartagriculture.entity.Like;
import me.zxk.smartagriculture.entity.News;
import me.zxk.smartagriculture.entity.User;
import me.zxk.smartagriculture.repository.CommentRepository;
import me.zxk.smartagriculture.repository.LikeRepository;
import me.zxk.smartagriculture.repository.NewsRepository;
import me.zxk.smartagriculture.repository.UserRepository;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 评论服务
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CommentService {

    private final CommentRepository commentRepository;
    private final NewsRepository newsRepository;
    private final UserRepository userRepository;
    private final LikeRepository likeRepository;

    /**
     * 获取新闻评论列表
     */
    public Page<CommentResponse> getNewsComments(Long newsId, Pageable pageable, Long currentUserId) {
        // 检查新闻是否存在
        News news = newsRepository.findById(newsId)
                .orElseThrow(() -> new RuntimeException("新闻不存在"));
        
        if (news.getStatus() != 1) {
            throw new RuntimeException("新闻未发布或已下线");
        }
        
        // 查询评论列表
        Page<Comment> commentPage = commentRepository.findByNewsIdAndStatus(newsId, 1, pageable);
        
        // 转换为响应DTO
        Page<CommentResponse> responsePage = commentPage.map(comment -> {
            CommentResponse response = CommentResponse.fromEntity(comment);
            // 手动设置用户信息（因为懒加载）
            User user = userRepository.findById(comment.getUserId()).orElse(null);
            if (user != null) {
                response.setUser(new CommentResponse.UserInfo(
                    user.getId(), user.getNickname(), user.getAvatarUrl()));
            }
            return response;
        });
        
        // 如果用户已登录，设置点赞状态
        if (currentUserId != null) {
            setCommentLikeStatus(responsePage.getContent(), currentUserId);
        }
        
        return responsePage;
    }

    /**
     * 发表评论
     */
    @Transactional
    public CommentResponse postComment(Long newsId, Long userId, CommentRequest request) {
        // 检查新闻是否存在
        News news = newsRepository.findById(newsId)
                .orElseThrow(() -> new RuntimeException("新闻不存在"));
        
        if (news.getStatus() != 1) {
            throw new RuntimeException("新闻未发布或已下线");
        }
        
        // 检查用户是否存在
        User user = userRepository.findById(userId)
                .orElseThrow(() -> new RuntimeException("用户不存在"));
        
        // 创建评论
        Comment comment = new Comment();
        comment.setNewsId(newsId);
        comment.setUserId(userId);
        comment.setContent(request.getContent());
        comment.setStatus(1);
        
        Comment savedComment = commentRepository.save(comment);
        
        // 增加新闻评论数
        newsRepository.incrementCommentCount(newsId);
        
        log.info("用户 {} 对新闻 {} 发表评论: {}", userId, newsId, savedComment.getId());
        
        // 构建响应
        CommentResponse response = CommentResponse.fromEntity(savedComment);
        response.setUser(new CommentResponse.UserInfo(
            user.getId(), user.getNickname(), user.getAvatarUrl()));
        
        return response;
    }

    /**
     * 点赞/取消点赞评论
     */
    @Transactional
    public boolean toggleCommentLike(Long commentId, Long userId) {
        // 检查评论是否存在
        Comment comment = commentRepository.findById(commentId)
                .orElseThrow(() -> new RuntimeException("评论不存在"));
        
        if (comment.getStatus() != 1) {
            throw new RuntimeException("评论已删除");
        }
        
        // 检查是否已点赞
        boolean isLiked = likeRepository.existsByUserIdAndTargetIdAndTargetType(
                userId, commentId, Like.TargetType.COMMENT);
        
        if (isLiked) {
            // 取消点赞
            likeRepository.deleteByUserIdAndTargetIdAndTargetType(userId, commentId, Like.TargetType.COMMENT);
            commentRepository.decrementLikeCount(commentId);
            log.info("用户 {} 取消点赞评论: {}", userId, commentId);
            return false;
        } else {
            // 点赞
            Like like = new Like();
            like.setUserId(userId);
            like.setTargetId(commentId);
            like.setTargetType(Like.TargetType.COMMENT);
            likeRepository.save(like);
            
            commentRepository.incrementLikeCount(commentId);
            log.info("用户 {} 点赞评论: {}", userId, commentId);
            return true;
        }
    }

    /**
     * 删除评论（软删除）
     */
    @Transactional
    public void deleteComment(Long commentId, Long userId) {
        // 检查评论是否存在且属于当前用户
        Comment comment = commentRepository.findByIdAndUserId(commentId, userId)
                .orElseThrow(() -> new RuntimeException("评论不存在或无权删除"));
        
        if (comment.getStatus() != 1) {
            throw new RuntimeException("评论已删除");
        }
        
        // 软删除评论
        commentRepository.softDeleteByIdAndUserId(commentId, userId);
        
        // 减少新闻评论数
        newsRepository.decrementCommentCount(comment.getNewsId());
        
        log.info("用户 {} 删除评论: {}", userId, commentId);
    }

    /**
     * 设置评论列表的点赞状态
     */
    private void setCommentLikeStatus(List<CommentResponse> comments, Long userId) {
        if (comments.isEmpty()) {
            return;
        }
        
        // 获取所有评论ID
        List<Long> commentIds = comments.stream()
                .map(CommentResponse::getId)
                .collect(Collectors.toList());
        
        // 批量查询用户的点赞记录
        List<Like> userLikes = likeRepository.findByUserIdAndTargetIdsAndTargetType(
                userId, commentIds, Like.TargetType.COMMENT);
        
        // 转换为Set便于查找
        Set<Long> likedCommentIds = userLikes.stream()
                .map(Like::getTargetId)
                .collect(Collectors.toSet());
        
        // 设置点赞状态
        comments.forEach(comment -> comment.setIsLiked(likedCommentIds.contains(comment.getId())));
    }
}
